<?php
namespace App\Models\Cart;

use App\Models\Concerns\ModelMemorable;
use App\Models\Products\Product;
use App\Models\Products\ProductDescription;
use App\Models\Products\ProductDiscount;
use App\Models\Products\ProductSpecial;
use App\Services\Customers\AppCustomer;
use App\Services\Locale\Language;
use App\Services\MobileApp\AppEnv;
use Illuminate\Database\Eloquent\Builder;
use Illuminate\Database\Eloquent\Collection;
use Illuminate\Database\Eloquent\Model;
use Illuminate\Database\Eloquent\Relations\HasMany;
use Illuminate\Support\Carbon;

/**
 * Class Cart
 *
 * @property int cart_id
 * @property int api_id
 * @property int customer_id
 * @property int session_id - 会话 varchar(32)
 * @property int product_id - 商品
 * @property int quantity - 商品数量
 * @property int recurring_id - ?
 * @property array option
 * @property Carbon date_added
 * @property string name
 * @property string image
 * @property int product_total_quantity
 * @property int|string price
 * @property string symbol_left
 * @property string symbol_right
 * @property array|mixed option_names
 * @property int product_minimum
 * @property string special_price
 * @property Collection discounts
 * @property string weight_by_kg
 * @property string currency_settle_price
 * @property Product product
 *
 * @package App\Models\Cart
 *
 * @mixin Builder
 */
class Cart extends Model
{
    use ModelMemorable;

    const QUANTITY_DEFAULT = 0; // 默认的购物车商品数量

    const API_ID_DEFAULT = 0;

    const SESSION_ID_LENGTH = 32; // varchar(32)
    const SESSION_ID_APP_PREFIX = 'app-';

    const RECURRING_ID_DEFAULT = 0;
    const CUSTOMER_ID_DEFAULT = 0;

    protected $table = 'cart';
    protected $guarded = [];

    protected $casts = [
        'option'     => 'json',
        'date_added' => 'datetime',
        'product_id' => 'int'
    ];

    protected $primaryKey = 'cart_id';

    public $timestamps = false;

    /**
     * @return \Illuminate\Database\Eloquent\Relations\BelongsTo
     */
    public function product()
    {
        /** @var \Illuminate\Database\Eloquent\Relations\BelongsTo|Product $product */
        $product = $this->belongsTo(Product::class, 'product_id', 'product_id');

        return $product->filterOnShelf();
    }

    /**
     * @return \Illuminate\Database\Eloquent\Relations\BelongsTo
     */
    public function productDescription()
    {
        return $this->belongsTo(ProductDescription::class, 'product_id', 'product_id')
            ->where('language_id', AppEnv::languageId());
    }

    /**
     * @return ProductDiscount|HasMany
     */
    public function productDiscounts()
    {
        /** @var HasMany|ProductDiscount $related */
        $related = $this->hasMany(ProductDiscount::class, 'product_id', 'product_id')
            ->where('customer_group_id', AppCustomer::groupId());

        return $related
            ->filterLimitSpecifiedRangeDate()
            ->orderBy('quantity','ASC')
            ->orderBy('priority','ASC');
    }

    /**
     * @return ProductSpecial|HasMany
     */
    public function productSpecials()
    {
        /** @var HasMany|ProductSpecial $related */
        $related = $this->hasMany(ProductSpecial::class, 'product_id', 'product_id')
            ->where('customer_group_id', AppCustomer::groupId());

        return $related->filterLimitSpecifiedRangeDate()
            ->orderBy('priority','ASC');
    }


    /**
     * @link https://secure.php.net/manual/en/function.openssl-random-pseudo-bytes.php - 文档
     *
     * @see \Session::start - dw-oc/system/library/session.php
     */
    static public function newSessionId(): string
    {
        $prefix_rand_str = self::SESSION_ID_APP_PREFIX . bin2hex(openssl_random_pseudo_bytes(self::SESSION_ID_LENGTH));

        return substr($prefix_rand_str, 0, self::SESSION_ID_LENGTH);
    }
}
